package com.ray.export.runner;

import com.ray.export.empty.Empty;
import com.ray.export.runner.common.*;
import com.ray.export.runner.confirm.*;
import com.ray.export.runner.exports.*;
import com.ray.export.runner.imports.DataVerificationRunner;
import com.ray.export.runner.imports.FileStoreRunner;
import com.ray.export.runner.imports.HeadReadRunner;
import com.ray.export.strategy.async.BeforeAsync;
import com.ray.export.strategy.data.DataHandling;
import com.ray.export.strategy.data.DataLog;
import com.ray.export.strategy.data.DataTransform;
import com.ray.export.strategy.data.DataVerification;
import com.ray.export.strategy.exports.*;
import com.ray.export.strategy.file.*;
import com.ray.export.strategy.result.Result;
import com.ray.export.strategy.result.Success;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @author bo shen
 * @Description: 策略工厂
 * @Class: RunnerFactory
 * @Package com.ray.strategy
 * @date 2019/11/21 14:04
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
public class RunnerFactory {

    private static Map<Class<?>,Runner> runnerMap = new HashMap<Class<?>,Runner>();

    static {
        //通用
        addRunner(Result.class,new ResultRunner());
        addRunner(Success.class,new SuccessRunner());
        addRunner(Error.class,new ErrorRunner());
        addRunner(BeforeAsync.class,new BeforeAsyncRunner());
        //导入流程
        addRunner(FileStore.class,new FileStoreRunner());
        addRunner(DataVerification.class,new DataVerificationRunner());
        addRunner(DataLog.class,new DataLogRunner());
        addRunner(HeadRead.class,new HeadReadRunner());
        //导入流程确认
        addRunner(FileLoad.class,new FileLoadRunner());
        addRunner(FileVerification.class,new FileVerificationRunner());
        addRunner(FileTemplate.class,new FileTemplateRunner());
        addRunner(FileContentRead.class,new FileContentReadRunner());
        addRunner(DataTransform.class,new DataTransformRunner());
        addRunner(DataHandling.class,new DataHandlingRunner());
        //导出流程
        addRunner(DataCount.class, new DataCountRunner());
        addRunner(PageVerification.class, new PageVerificationRunner());
        addRunner(AsyncVerification.class, new AsyncVerificationRunner());
        addRunner(DataExport.class, new DataExportRunner());
        addRunner(ExportFileStore.class, new ExportFileStoreRunner());

    }



    /**链头**/
    private  RunnerChain head;

    /**链尾**/
    private RunnerChain tail;

    /**
     * 添加一个执行器 如果key相同会替换原来的执行器
     *
     * @param clazz
     * @param runner
     */
    public static void addRunner(Class<?> clazz, Runner runner) {
        Assert.notNull(clazz, "参数[clazz]不能为空");
        Assert.notNull(runner, "参数[actuator]不能为空");
        if (log.isDebugEnabled()) {
            log.debug("执行者{},{}被添加", clazz, runner.getClass().getName());
        }
        runnerMap.put(clazz, runner);
    }

    /**
     * 添加一个runner
     * @param runner
     * @return
     */
    public  RunnerFactory add(Runner runner) {
        RunnerChain runnerChain = new RunnerChain();
        runnerChain.setRunner(runner);
        if(ObjectUtils.isEmpty(head)){
            this.head = runnerChain;
        }else {
            this.tail.setNext(runnerChain);
        }
        this.tail = runnerChain;
        return  this;
    }

    /**
     * 添加一个执行者对象
     * @param clazz
     * @return
     */
    public RunnerFactory add(Class<?> clazz,Class<?> interfaceClass) {
        //Empty 不需要执行
        if(clazz == Empty.class){
            return this;
        }
        RunnerChain runnerChain = new RunnerChain();
        //获实际的执行者
        Runner runner = runnerMap.get(interfaceClass);
        if(ObjectUtils.isEmpty(runner)){
            throw new RuntimeException(String.format("没有对应的执行器:%s",clazz.getName()));
        }
        runnerChain.setRunner(runner);
        if(ObjectUtils.isEmpty(head)){
            this.head = runnerChain;
        }else {
            this.tail.setNext(runnerChain);
        }
        this.tail = runnerChain;
        return  this;
    }


    public  static Runner getRunner(Class<?> clazz){
        Runner runner = runnerMap.get(clazz);
        if(ObjectUtils.isEmpty(runner)){
            throw new RuntimeException(String.format("没有对应的执行器:%s",clazz.getName()));
        }
        return  runner;
    }

    /**
     * 获取链条头部
     * @return
     */
    public  RunnerChain getHead(){
        return  head;
    }


}
